home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 476-500 / disk_485 / spades / spades.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  62KB  |  1,820 lines

  1. /**********************************************************
  2. * PROGRAM: Spades                                         *
  3. * AUTHOR: Gregory M. Stelmack                             *
  4. * COMPILER: SAS/C 5.10                                    *
  5. *      Copyright (C) 1988 Lattice, Inc.                   *
  6. *      Copyright (C) 1990 SAS Institute, Inc.             *
  7. * VESRION DATES:                                          *
  8. *      Version 1.0  -- February 5, 1990                   *
  9. *      Version 1.1  -- April 28, 1990                     *
  10. *           Images used for cards -- file "Spades.images" *
  11. *           must be in current directory to run.          *
  12. *           Title graphics added. New routine for         *
  13. *           choosing dealer.                              *
  14. *      Version 1.11 -- August 23, 1990                    *
  15. *           Fixed memory freeing bug. Added some prompts. *
  16. *      Version 1.12 -- October 3, 1990                    *
  17. *           Removed LIBRARY_VERSION from OpenLibrary()    *
  18. *           calls, replacing it with zero. An attempt to  *
  19. *           let it run under pre-1.3.                     *
  20. *      Version 1.20 -- April 4, 1991                      *
  21. *           Error messages now pause. Revised strategy.   *
  22. *           Window can be sized and dragged, and screen   *
  23. *           moved to back to allow other things to be     *
  24. *           done.                                         *
  25. *                                                         *
  26. * Tab stops set to 8,16,24,32,40,48,... for this listing. *
  27. **********************************************************/
  28.  
  29. /* Include files */
  30.  
  31. #include <exec/types.h>
  32. #include <exec/memory.h>
  33. #include <intuition/intuition.h>
  34. #include <exec/libraries.h>
  35. #include <graphics/gfxmacros.h>
  36. #include <proto/all.h>
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <math.h>
  40. #include <time.h>
  41. #include <string.h>
  42. #include <fcntl.h>
  43. #include "Spades.proto"
  44.  
  45. /* Structures needed for libraries */
  46.  
  47. struct IntuitionBase *IntuitionBase;
  48. struct GfxBase       *GfxBase;
  49. struct Library       *DiskfontBase;
  50.  
  51. /* Intuition Structures */
  52.  
  53. struct Screen       *CustScr;
  54. struct Window       *Wdw;
  55. struct Viewport     *WVP;
  56. struct IntuiMessage *Message;
  57.  
  58. /************** Program Constants **************/
  59. #define RP       Wdw->RPort      /* Raster Port for Graphics Routines */
  60. #define PENS        8            /* Number of Pens                    */
  61. #define DEPTH       3            /* Number of BitPlanes               */
  62. #define MLEFT       1            /* Left Mouse Button Pressed         */
  63. #define MRIGHT      2            /* Right Mouse Button Pressed        */
  64.  
  65. #define DIAMONDS    0            /* Suit Definitions */
  66. #define CLUBS       1
  67. #define HEARTS      2
  68. #define SPADES      3
  69.  
  70. #define WHITE  0xFFF             /* Palette Data */
  71. #define RED    0xF00
  72. #define GREEN  0x0F0
  73. #define BLUE   0x00F
  74. #define CYAN   0x0FF
  75. #define PURPLE 0xF0F
  76. #define YELLOW 0xFF0
  77. #define BLACK  0x000
  78.  
  79. #define CARDMEMSIZE  52*126*2*3  /* Memory needed for card data */
  80.  
  81. /************** Color Map Data *****************/
  82. static USHORT colormap[PENS] =
  83. {
  84.     BLUE,      /* Pen  0 */
  85.     BLACK,     /* Pen  1 */
  86.     RED,       /* Pen  2 */
  87.     GREEN,     /* Pen  3 */
  88.     WHITE,     /* Pen  4 */
  89.     YELLOW,    /* Pen  5 */
  90.     PURPLE,    /* Pen  6 */
  91.     CYAN       /* Pen  7 */
  92. };
  93.  
  94. #define BLUP 0
  95. #define BLKP 1
  96. #define REDP 2
  97. #define GRNP 3
  98. #define WHTP 4
  99. #define YELP 5
  100. #define PURP 6
  101. #define CYNP 7
  102.  
  103. /************** Text Structure *****************/
  104. struct TextAttr StdFont =
  105. {
  106.     "topaz.font",
  107.     TOPAZ_EIGHTY,
  108.     FS_NORMAL,
  109.     FPF_ROMFONT,
  110. };
  111.  
  112. /*********** NewScreen Structure **********/
  113. struct NewScreen NewCustScr =
  114. {
  115.     0,0,            /* Left Edge, Top Edge       */
  116.     320,200,DEPTH,  /* Width, Height, Depth      */
  117.     WHTP,BLUP,      /* Detail Pen, Block Pen     */
  118.     NULL,           /* View Mode                 */
  119.     CUSTOMSCREEN,   /* Screen Type               */
  120.     &StdFont,       /* Pointer to Font           */
  121.     NULL,           /* Pointer to Title Text     */
  122.     NULL,           /* Pointer to Screen Gadgets */
  123.     NULL,           /* Pointer to CustomBitMap   */
  124. };
  125.  
  126. /**************** Gadgets ******************/
  127.  
  128. struct IntuiText IText1 = {
  129.         YELP,BLKP,JAM2,    /* front and back text pens, drawmode and fill byte */
  130.         -1,0,    /* XY origin relative to container TopLeft */
  131.         NULL,    /* font pointer or NULL for default */
  132.         "HIDE",    /* pointer to text */
  133.         NULL    /* next IntuiText structure */
  134. };
  135.  
  136. struct Gadget HideGadget = {
  137.     NULL,    /* next gadget */
  138.     265,1,    /* origin XY of hit box relative to window TopLeft */
  139.     32,8,    /* hit box width and height */
  140.     NULL,    /* gadget flags */
  141.     RELVERIFY+TOPBORDER,    /* activation flags */
  142.     BOOLGADGET+GZZGADGET,    /* gadget type flags */
  143.     NULL,   /* gadget border or image to be rendered */
  144.     NULL,    /* alternate imagery for selection */
  145.     &IText1,    /* first IntuiText structure */
  146.     NULL,    /* gadget mutual-exclude long word */
  147.     NULL,    /* SpecialInfo structure */
  148.     NULL,    /* user-definable data */
  149.     NULL    /* pointer to user-definable data */
  150. };
  151.  
  152. /*********** NewWindow Structure **********/
  153. struct NewWindow NewWdw =
  154. {
  155.     0,0,            /* Left Edge, Top Edge          */
  156.     320,200,        /* Width, Height                */
  157.     BLKP,WHTP,      /* Block Pen, Detail Pen        */
  158.     MOUSEBUTTONS | CLOSEWINDOW | GADGETUP,   /* IDCMP Flags */
  159.     SMART_REFRESH | ACTIVATE | GIMMEZEROZERO | RMBTRAP | WINDOWCLOSE,
  160.     &HideGadget,    /* Pointer to First Gadget      */
  161.     NULL,           /* Pointer to Check Mark image  */
  162.     "Spades 1.20, by Greg Stelmack",       /* Title */
  163.     NULL,           /* Pointer to Screen structure  */
  164.     NULL,           /* Pointer to custom Bit Map    */
  165.     320,100,        /* Minimum Width, Height        */
  166.     0,0,            /* Maximum Width, Height        */
  167.     CUSTOMSCREEN    /* Type of Screen it resides on */
  168. };
  169.  
  170. /************************* Image Data *************************/
  171. struct Image CardImage =
  172. {
  173.   0, 0,                        /* LeftEdge, TopEdge     */
  174.   42, 42, 3,                   /* Width, Height, Depth  */
  175.   NULL,                        /* Image Data            */
  176.   7, 0,                        /* PlanePick, PlaneOnOff */
  177.   NULL                         /* *NextImage            */
  178. };
  179.  
  180. #include "Spades.h"
  181.  
  182. /*************************** Arrays ***************************/
  183.  
  184. /***************************************
  185. * Deck: status of cards.               *
  186. *      0 = Undealt or played.          *
  187. *  1 thru 4 = Player who holds card.   *
  188. ***************************************/
  189. int Deck[52] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  190.                 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  191.  
  192. /***************************************
  193. * Hand: cards in each player's hand.   *
  194. *      0 = Played.                     *
  195. *  1 thru 52 = Card number.            *
  196. ***************************************/
  197. int Hand[4][13] = { {0,0,0,0,0,0,0,0,0,0,0,0,0},
  198.                     {0,0,0,0,0,0,0,0,0,0,0,0,0},
  199.                     {0,0,0,0,0,0,0,0,0,0,0,0,0},
  200.                     {0,0,0,0,0,0,0,0,0,0,0,0,0} };
  201.  
  202. /********************************************
  203. * Bid: number of tricks bid by each player. *
  204. ********************************************/          
  205. int Bid[4] = {0,0,0,0};
  206.  
  207. /********************************************
  208. * Mode: aggressiveness of each player.      *
  209. *   The number in this array is added to    *
  210. *   the strength of the hand to determine   *
  211. *   the number of tricks to bid. Higher     *
  212. *   number equals more tricks.              *
  213. ********************************************/
  214. int Mode[4] = {0,0,0,0};
  215.   
  216. /********************************************
  217. * HighCardLeft: the highest unplayed card   *
  218. *   in each suit.                           *
  219. ********************************************/
  220. int HighCardLeft[4] = {0,0,0,0};
  221.  
  222. /********************************************
  223. * Card: the card played in a trick by each  *
  224. *   player.                                 *
  225. ********************************************/
  226. int Card[4] = {0,0,0,0};
  227.   
  228. /********************************************
  229. * Value: the point value of each card held  *
  230. *   in a hand. Used by computer to determine*
  231. *   which card to play.                     *
  232. ********************************************/
  233. int Value[13] = {0,0,0,0,0,0,0,0,0,0,0,0,0};
  234.  
  235. /********************************************
  236. * SuitNumber: the number of cards in each   *
  237. *   suit held by a player.                  *
  238. ********************************************/
  239. int SuitNumber[4] = {0,0,0,0};
  240.   
  241. /********************************************
  242. * CardX & CardY: The X and Y positions for  *
  243. *   the played card for each player.        *
  244. * MsgX & MsgY: The X and Y positions for    *
  245. *   single character messages for each      *
  246. *   player.                                 *
  247. ********************************************/
  248. int CardX[4] = {100,1,100,209};
  249. int CardY[4] = {99,60,1,60};
  250.   
  251. int MsgX[4] = {116,45,116,195};
  252. int MsgY[4] = {96,84,50,84};
  253.   
  254. /********************************************
  255. * OutOfSuit: Whether or not a player is out *
  256. *   of a suit.                              *
  257. ********************************************/
  258. BOOL OutOfSuit[4][4] = { {0,0,0,0},
  259.                          {0,0,0,0},
  260.                          {0,0,0,0},
  261.                          {0,0,0,0} };
  262.                           
  263. /******************** Other Global Variables ******************/
  264. char *String = "      "; /* Temporary String Storage */
  265.  
  266. int PlayerScore=0, CompScore=0, PlayerTricks=0, CompTricks=0;
  267. int HandLead=0, Button=0, TrickLead=0, PlayerBid=0, CompBid=0;
  268. int ShortSuit=0, LongSuit=0, HighCard=0, Winner=0;
  269. BOOL SpadePlayed=FALSE, AllDone=FALSE, ScreenOpen=FALSE;
  270. char *CardData;
  271.  
  272. SHORT Mx=0, My=0;        /* Mouse Coordinates */
  273.  
  274. /********************* Program Begins Here ********************/
  275.  
  276. /**********************************************************
  277. * Function: main                                          *
  278. * Purpose: Open everything, play the game, close          *
  279. *          everything.                                    *
  280. **********************************************************/
  281. main()
  282. {
  283.         int fh;
  284.         unsigned int count=0;
  285.         
  286.     /* Open the Intuition and Graphics libraries. */
  287.   
  288.     IntuitionBase = (struct IntuitionBase *)
  289.          OpenLibrary("intuition.library",0);
  290.     if (IntuitionBase == NULL) 
  291.                 PError("Can't open Intuition Library");
  292.     
  293.     GfxBase = (struct GfxBase *)
  294.          OpenLibrary("graphics.library",0);
  295.     if (GfxBase == NULL)
  296.                 PError("Can't open Graphics Library");
  297.  
  298.         /* Load Graphic Images */
  299.   
  300.         CardData = (char *)AllocMem(CARDMEMSIZE,MEMF_CHIP);
  301.         if (!CardData)
  302.                 PError("Could not allocate image memory!");
  303.         fh = open("Spades.images",O_RDONLY,0);
  304.         if (fh==-1)
  305.                 PError("Can't open images file!");
  306.         count = read(fh,CardData,CARDMEMSIZE);
  307.         if (count==-1)
  308.                 PError("Error reading images file!");
  309.  
  310.         /* Open the screen and window */
  311.     
  312.     if ((NewWdw.Screen = CustScr =
  313.       (struct Screen *)OpenScreen(&NewCustScr)) == NULL)
  314.                 PError("Can't open new screen");
  315.       
  316.         ScreenOpen = TRUE;
  317.         
  318.     if (( Wdw = (struct Window *)OpenWindow(&NewWdw)) == NULL)
  319.                 PError("Can't open new window");
  320.       
  321.     /* Find the viewport and load color map */
  322.     
  323.     WVP = (struct ViewPort *)ViewPortAddress(Wdw);
  324.     LoadRGB4(WVP,&colormap[0],PENS);
  325.     
  326.         /* Seed random number generator with TIMER */
  327.   
  328.         srand(time(NULL));
  329.   
  330.     
  331.         /* Start Game */
  332.     
  333.         Spades();
  334.         
  335.         /* Close Everything */
  336.   
  337.         WrapUp();
  338. }
  339.  
  340. /**********************************************************
  341. * Function: PError                                        *
  342. * Parameters: s -- pointer to string to print             *
  343. * Return Values: None                                     *
  344. * Purpose: Handle a fatal error                           *
  345. **********************************************************/
  346. void PError(s)
  347. char *s;
  348. {
  349.         char c=' ';
  350.         
  351.         printf("%s\n",s);
  352.         if (!ScreenOpen)
  353.         {
  354.                 printf("Please press RETURN...");
  355.                 c=getchar();
  356.         }
  357.         WrapUp();
  358. }
  359.  
  360. /**********************************************************
  361. * Function: WrapUp                                        *
  362. * Parameters: none                                        *
  363. * Return Values: none                                     *
  364. * Purpose: close everything and exit                      *
  365. **********************************************************/
  366. void WrapUp()
  367. {
  368.         if (CardData)      FreeMem((char *)CardData,CARDMEMSIZE);
  369.     if (Wdw)           CloseWindow(Wdw);
  370.     if (CustScr)       CloseScreen(CustScr);
  371.     if (GfxBase)       CloseLibrary(GfxBase);
  372.     if (IntuitionBase) CloseLibrary(IntuitionBase);
  373.         exit(0);
  374. }
  375.  
  376. /**********************************************************
  377. * Function: Spades                                        *
  378. * Parameters: None                                        *
  379. * Return Values: None                                     *
  380. * Purpose: Play a game of spades. Loop until someone      *
  381. *          scores 500.                                    *
  382. **********************************************************/
  383. void Spades()
  384. {
  385.         Title();
  386.  
  387.         AllDone=FALSE;
  388.   
  389.         /* Loop until player no longer wants to play. */
  390.   
  391.         while (!AllDone)
  392.         {
  393.                 PlayerScore=CompScore=0;
  394.                 HandLead=FindDealer();
  395.     
  396.                 /* Loop until someone reaches 500 and there is no tie. */
  397.     
  398.                 while (((PlayerScore<500)&&(CompScore<500))||(PlayerScore==CompScore))
  399.                 {
  400.                         SetUpScreen();
  401.                         InitVars();
  402.                         PrintScore();
  403.                         DealCards();
  404.                         GetBids();
  405.                         PrintBids();
  406.                         PlayHand();
  407.                 }
  408.     
  409.                 FinishRoutine();
  410.         }
  411. }
  412.  
  413. /**********************************************************
  414. * Function: Title                                         *
  415. * Parameters: none                                        *
  416. * Return Values: none                                     *
  417. * Purpose: draw title graphics.                           *
  418. **********************************************************/
  419. void Title()
  420. {
  421.         int i=0;
  422.   
  423.         SetRast(RP,BLUP);              /* Clear screen */
  424.         SetAPen(RP,YELP);
  425.         SetBPen(RP,BLUP);
  426.   
  427.         /* Draw card backs */
  428.   
  429.         for (i=0; i<6 ; i++)
  430.         {
  431.                 DrawImage(RP,&Image25,(i*50)+15,65);
  432.         }
  433.   
  434.         /* Flip S */
  435.   
  436.         Delay(5);
  437.         DrawImage(RP,&Image24,15,65);
  438.         Delay(5);
  439.         DrawImage(RP,&Image23,15,65);
  440.         Delay(5);
  441.         DrawImage(RP,&Image22,15,65);
  442.         Delay(5);
  443.         DrawImage(RP,&Image21,15,65);
  444.         Delay(5);
  445.         DrawImage(RP,&Image17,15,65);
  446.         Delay(5);
  447.         DrawImage(RP,&Image18,15,65);
  448.         Delay(5);
  449.         DrawImage(RP,&Image19,15,65);
  450.         Delay(5);
  451.         DrawImage(RP,&Image20,15,65);
  452.   
  453.         /* Flip P */
  454.   
  455.         Delay(5);
  456.         DrawImage(RP,&Image24,65,65);
  457.         Delay(5);
  458.         DrawImage(RP,&Image23,65,65);
  459.         Delay(5);
  460.         DrawImage(RP,&Image22,65,65);
  461.         Delay(5);
  462.         DrawImage(RP,&Image21,65,65);
  463.         Delay(5);
  464.         DrawImage(RP,&Image13,65,65);
  465.         Delay(5);
  466.         DrawImage(RP,&Image14,65,65);
  467.         Delay(5);
  468.         DrawImage(RP,&Image15,65,65);
  469.         Delay(5);
  470.         DrawImage(RP,&Image16,65,65);
  471.   
  472.         /* Flip A */
  473.   
  474.         Delay(5);
  475.         DrawImage(RP,&Image24,115,65);
  476.         Delay(5);
  477.         DrawImage(RP,&Image23,115,65);
  478.         Delay(5);
  479.         DrawImage(RP,&Image22,115,65);
  480.         Delay(5);
  481.         DrawImage(RP,&Image21,115,65);
  482.         Delay(5);
  483.         DrawImage(RP,&Image9,115,65);
  484.         Delay(5);
  485.         DrawImage(RP,&Image10,115,65);
  486.         Delay(5);
  487.         DrawImage(RP,&Image11,115,65);
  488.         Delay(5);
  489.         DrawImage(RP,&Image12,115,65);
  490.   
  491.         /* Flip D */
  492.   
  493.         Delay(5);
  494.         DrawImage(RP,&Image24,165,65);
  495.         Delay(5);
  496.         DrawImage(RP,&Image23,165,65);
  497.         Delay(5);
  498.         DrawImage(RP,&Image22,165,65);
  499.         Delay(5);
  500.         DrawImage(RP,&Image21,165,65);
  501.         Delay(5);
  502.         DrawImage(RP,&Image5,165,65);
  503.         Delay(5);
  504.         DrawImage(RP,&Image6,165,65);
  505.         Delay(5);
  506.         DrawImage(RP,&Image7,165,65);
  507.         Delay(5);
  508.         DrawImage(RP,&Image8,165,65);
  509.   
  510.         /* Flip E */
  511.   
  512.         Delay(5);
  513.         DrawImage(RP,&Image24,215,65);
  514.         Delay(5);
  515.         DrawImage(RP,&Image23,215,65);
  516.         Delay(5);
  517.         DrawImage(RP,&Image22,215,65);
  518.         Delay(5);
  519.         DrawImage(RP,&Image21,215,65);
  520.         Delay(5);
  521.         DrawImage(RP,&Image1,215,65);
  522.         Delay(5);
  523.         DrawImage(RP,&Image2,215,65);
  524.         Delay(5);
  525.         DrawImage(RP,&Image3,215,65);
  526.         Delay(5);
  527.         DrawImage(RP,&Image4,215,65);
  528.   
  529.         /* Flip S */
  530.   
  531.         Delay(5);
  532.         DrawImage(RP,&Image24,265,65);
  533.         Delay(5);
  534.         DrawImage(RP,&Image23,265,65);
  535.         Delay(5);
  536.         DrawImage(RP,&Image22,265,65);
  537.         Delay(5);
  538.         DrawImage(RP,&Image21,265,65);
  539.         Delay(5);
  540.         DrawImage(RP,&Image17,265,65);
  541.         Delay(5);
  542.         DrawImage(RP,&Image18,265,65);
  543.         Delay(5);
  544.         DrawImage(RP,&Image19,265,65);
  545.         Delay(5);
  546.         DrawImage(RP,&Image20,265,65);
  547.   
  548.         /* Prompt for pause */
  549.   
  550.         Move(RP,50,180);
  551.         Text(RP,"Click any mouse button...",25);
  552.   
  553.         ReadMouse();                   /* Pause for click */
  554. }
  555.  
  556. /**********************************************************
  557. * Function: FindDealer                                    *
  558. * Parameters: none                                        *
  559. * Return Values: the player determined to initially deal. *
  560. * Purpose: find out who deals first in a game.            *
  561. **********************************************************/
  562. int FindDealer()
  563. {
  564.         int player=0, card=0, i;
  565.         BOOL done=FALSE;
  566.  
  567.         SetRast(RP,BLUP);              /* Clear Screen */  
  568.         SetAPen(RP,YELP);
  569.         SetBPen(RP,BLUP);
  570.   
  571.         for (i=0 ; i<52 ; i++) Deck[i]=0;    /* Set deck to undealt */
  572.   
  573.         Move(RP,70,70);                /* Warn player of what's happening */
  574.         Text(RP,"Ace of Spades",13);
  575.         Move(RP,98,78);
  576.         Text(RP,"deals",5);
  577.   
  578.         while(!done)                   /* Loop until dealer found */
  579.         {
  580.                 while(Deck[card=rand()%52]) ;      /* Find undealt card */
  581.                 Deck[card]=1;                      /* Mark card as dealt */
  582.                 DrawCard(CardX[player],CardY[player],card);
  583.                                                    /* Draw card */
  584.                 Delay(10);                         /* Pause */
  585.                 if (card==51)                      /* Ace of Spades */
  586.                 {
  587.                         done=TRUE;
  588.                         Move(RP,MsgX[player],MsgY[player]);
  589.                         Text(RP,"*",1);
  590.                 }
  591.                 player=(++player)%4;   /* Increment player */
  592.         }
  593.   
  594.         Move(RP,200,150);              /* Wait for player */
  595.         Text(RP,"Click mouse",11);
  596.         ReadMouse();
  597.   
  598.         SetRast(RP,BLUP);
  599.         return((++player)%4);          /* Must return player 2 to left of */
  600.                                        /* dealer. Program will later */
  601.                                        /* decrement player to find lead */
  602.                                        /* who should be to left of dealer */
  603. }
  604.   
  605. /**********************************************************
  606. * Function: SetUpScreen                                   *
  607. * Parameters: none                                        *
  608. * Return Values: none                                     *
  609. * Purpose: gets the screen ready for a new hand.          *
  610. **********************************************************/
  611. void SetUpScreen()
  612. {
  613.         /* Clear the Screen */
  614.   
  615.         SetRast(RP,BLUP);
  616.         SetAPen(RP,YELP);
  617.         SetBPen(RP,BLKP);
  618.         
  619.         /* Draw the Score Box */
  620.   
  621.         Move(RP,215,6);
  622.         Text(RP," YOU   CMP ",11);
  623.         Move(RP,215,14);
  624.         Text(RP,"SCORE SCORE",11);
  625.         Move(RP,215,22);
  626.         Text(RP,"           ",11);
  627.         Move(RP,215,30);
  628.         Text(RP," BID   BID ",11);
  629.         Move(RP,215,38);
  630.         Text(RP,"           ",11);
  631.         Move(RP,215,46);
  632.         Text(RP,"TRICK TRICK",11);
  633.         Move(RP,215,54);
  634.         Text(RP,"           ",11); 
  635.         SetAPen(RP,WHTP);
  636.         Move(RP,215,7);
  637.         Draw(RP,302,7);
  638.         Move(RP,258,0);
  639.         Draw(RP,258,55);
  640. }
  641.  
  642. /**********************************************************
  643. * Function: InitVars                                      *
  644. * Parameters: none                                        *
  645. * Return Values: none                                     *
  646. * Purpose: Initialize variables and arrays for a new hand.*
  647. **********************************************************/
  648. void InitVars()
  649. {
  650.         int i;
  651.   
  652.         /* Set Leader */
  653.   
  654.         HandLead=(--HandLead+4)%4;
  655.         TrickLead=HandLead;
  656.   
  657.         /* Reset HighCardLeft */
  658.   
  659.         HighCardLeft[0]=12;
  660.         HighCardLeft[1]=12;
  661.         HighCardLeft[2]=12;
  662.         HighCardLeft[3]=12;
  663.   
  664.         /* Reset OutOfSuit */
  665.   
  666.         for (i=0 ; i<4 ; i++)
  667.         {
  668.                 OutOfSuit[i][DIAMONDS]=FALSE;
  669.                 OutOfSuit[i][CLUBS]   =FALSE;
  670.                 OutOfSuit[i][HEARTS]  =FALSE;
  671.                 OutOfSuit[i][SPADES]  =FALSE;
  672.         }
  673.   
  674.         /* Determine Modes */
  675.   
  676.         for (i=0 ; i<4 ; i++)
  677.         {
  678.                 Mode[i]=0;
  679.                 if (i==HandLead) Mode[i]+=2;   /* Leader should bid higher */
  680.                 if (i==0||i==2)                /* Human players -- check score */
  681.                 {
  682.                         if ((PlayerScore>400)&&(CompScore<350)) Mode[i]-=1;
  683.                         if (PlayerScore<(CompScore-100)) Mode[i]+=1;
  684.                         if (PlayerScore<(CompScore-200)) Mode[i]+=1;
  685.                         if (PlayerScore>(CompScore+100)) Mode[i]-=1;
  686.                 }
  687.                 if (i==1||i==3)                /* Computer players -- check score */
  688.                 {
  689.                         if ((CompScore>400)&&(PlayerScore<350)) Mode[i]-=1;
  690.                         if (CompScore<(PlayerScore-100)) Mode[i]+=1;
  691.                         if (CompScore<(PlayerScore-200)) Mode[i]+=1;
  692.                         if (CompScore>(PlayerScore+100)) Mode[i]-=1;
  693.                 }
  694.         }
  695. }
  696.  
  697. /**********************************************************
  698. * Function: DealCards                                     *
  699. * Parameters: none                                        *
  700. * Return Values: none                                     *
  701. * Purpose: Shuffle & deal the deck to the players.        *
  702. **********************************************************/
  703. void DealCards()
  704. {
  705.         int i,j,player,cardnum[4];
  706.   
  707.         for (i=0 ; i<4 ; i++) cardnum[i]=0; /* Reset cards for each player */
  708.         for (i=0 ; i<52 ; i++) Deck[i]=0;   /* Set whole deck to undealt */
  709.   
  710.         /* Shuffle and Deal Deck */
  711.   
  712.         for (i=0 ; i<52 ; i++)
  713.         {
  714.                 while(Deck[j=rand()%52]) ;       /* Find undealt card */
  715.                 Deck[j]=((i/13)+1);              /* Store owning player */
  716.         }
  717.   
  718.         /* Transfer cards to player hands */
  719.   
  720.         for (i=0 ; i<52 ; i++)
  721.         {
  722.                 player=Deck[i]-1;                     /* Get owning player */
  723.                 Hand[player][cardnum[player]++]=i+1;  /* Store card, increment counter */
  724.         }
  725. }
  726.  
  727. /**********************************************************
  728. * Function: ShowHand                                      *
  729. * Parameters: none                                        *
  730. * Return Values: none                                     *
  731. * Purpose: To display the player's hand.                  *
  732. **********************************************************/
  733. void ShowHand()
  734. {
  735.         int i;
  736.   
  737.         /* Erase old hand */
  738.   
  739.         SetAPen(RP,BLUP);
  740.         SetOPen(RP,BLUP);
  741.         RectFill(RP,21,145,183,186);
  742.  
  743.         /* Draw each card, overlaying part of the previous one */
  744.  
  745.         for (i=0 ; i<13 ; i++)
  746.         {
  747.                 if (Hand[0][i])  /* Only draw if card hasn't been played */
  748.                         DrawCard(((i*10)+21),145,((Hand[0][i])-1));
  749.         }
  750. }
  751.  
  752. /**********************************************************
  753. * Function: GetBids                                       *
  754. * Parameters: none                                        *
  755. * Return values: none                                     *
  756. * Purpose: Get each player's bid.                         *
  757. **********************************************************/
  758. void GetBids()
  759. {
  760.         int i;
  761.   
  762.         for (i=0 ; i<4 ; i++) Bid[i]=0;   /* Reset bids for each player */
  763.   
  764.         /* Loop through each player */
  765.   
  766.         i=HandLead;
  767.         do
  768.         {
  769.                 if (i)
  770.                         Bid[i]=CalcBid(i);        /* Computer Player */
  771.                 else 
  772.                         Bid[i]=GetPlayerBid();    /* Human Player */
  773.                 i=(++i)%4;
  774.         }  while (i!=HandLead);
  775.   
  776.         /* Calculate team contracts */
  777.   
  778.         PlayerBid=Bid[0]+Bid[2];
  779.         CompBid=Bid[1]+Bid[3];
  780.   
  781.         /* Pause for click */
  782.  
  783.         SetAPen(RP,YELP);
  784.         Move(RP,200,150);
  785.         Text(RP,"Click mouse",11);
  786.         ReadMouse();
  787.         Move(RP,200,150);
  788.         Text(RP,"           ",11);
  789.         
  790.         /* Erase Bids */
  791.   
  792.         SetBPen(RP,BLUP);
  793.         for (i=0 ; i<4 ; i++)
  794.         {
  795.                 Move(RP,MsgX[i],MsgY[i]);
  796.                 Text(RP," ",1);
  797.         }
  798. }
  799.  
  800. /**********************************************************
  801. * Function: GetPlayerBid                                  *
  802. * Parameters: none                                        *
  803. * Return Values: bid -- number of tricks bid              *
  804. * Purpose: Get the human player's bid. Could use gadgets, *
  805. *          but this is easier to program.                 *
  806. **********************************************************/
  807. int GetPlayerBid()
  808. {
  809.         int bid=1,length;
  810.         BOOL havebid=FALSE;
  811.  
  812.         ShowHand();
  813.  
  814.         /* Draw input box */
  815.   
  816.         SetAPen(RP,YELP);
  817.         SetBPen(RP,BLKP);
  818.         Move(RP,258,142);
  819.         Text(RP,"BID",3);
  820.         Move(RP,250,150);
  821.         Text(RP,"  +  ",5);
  822.         Move(RP,250,158);
  823.         Text(RP,"   OK",5);
  824.         Move(RP,250,166);
  825.         Text(RP,"  -  ",5);
  826.   
  827.         /* Loop until OK is clicked */
  828.   
  829.         while(!havebid)
  830.         {
  831.     
  832.                 /* Draw Current Bid */
  833.     
  834.                 SetAPen(RP,GRNP);
  835.                 SetBPen(RP,BLKP);
  836.                 Move(RP,250,158);
  837.                 Text(RP,"  ",2);
  838.                 itoa(bid,String);
  839.                 length=strlen(String);
  840.                 Move(RP,(258-(4*length)),158);
  841.                 Text(RP,String,length);
  842.     
  843.                 /* Wait for Mouse input */
  844.     
  845.                 ReadMouse();
  846.                 if (Button==MLEFT)    /* Left Button Pressed */
  847.                 {
  848.                         if ((Mx>265)&&(Mx<274)&&(My>143)&&(My<152)) bid++;  /* plus sign  */
  849.                         if ((Mx>273)&&(Mx<290)&&(My>151)&&(My<160)) havebid=TRUE; /* OK   */
  850.                         if ((Mx>265)&&(Mx<274)&&(My>159)&&(My<168)) bid--;  /* minus sign */
  851.                 }
  852.                 if (Button==MRIGHT)   /* Right Button Pressed */
  853.                 {
  854.                         bid=CalcBid(0);     /* Suggest a Bid */
  855.                 }
  856.     
  857.                 /* Make sure bid is valid */
  858.     
  859.                 if (bid<1)  bid=1;
  860.                 if (bid>12) bid=12;
  861.         }
  862.   
  863.         /* Erase Input Box */
  864.   
  865.         SetAPen(RP,BLUP);
  866.         SetOPen(RP,BLUP);
  867.         RectFill(RP,250,135,291,168);
  868.   
  869.         /* Display the bid */
  870.   
  871.         SetAPen(RP,YELP);
  872.         SetBPen(RP,BLUP);
  873.         itoa(bid,String);
  874.         Move(RP,MsgX[0],MsgY[0]);
  875.         Text(RP,String,strlen(String));
  876.   
  877.         /* Send the bid back */
  878.   
  879.         return(bid);
  880. }
  881.  
  882. /**********************************************************
  883. * Function: CalcBid                                       *
  884. * Parameters: player -- number of player to calculate for *
  885. * Return Values: bid -- number of tricks                  *
  886. * Purpose: To calculate the number of tricks bid by a     *
  887. *          player.                                        *
  888. **********************************************************/
  889. int CalcBid(player)
  890. int player;
  891. {
  892.         int i,j,numsuit,points,suit,bid;
  893.         int k,numspades;
  894.         
  895.         points=0;
  896.  
  897.         /* Calculate spades */
  898.   
  899.         numspades=0;
  900.     
  901.         /* Count Spades  */
  902.     
  903.         for (j=39 ; j<52 ; j++)
  904.                 if (Deck[j]==player+1) numspades++;
  905.  
  906.         numsuit = numspades;
  907.         
  908.         /* Add points for Spades -- if enough to cover, count it */
  909.  
  910.         for (j=51 ; j>38 ; j--)
  911.         {
  912.                 k = 12-(j%13);
  913.                 if ((Deck[j]==player+1)&&(numsuit>k))
  914.                 {
  915.                         points+=4;
  916.                         numspades=numsuit-k;    /* Used to make sure we don't
  917.                                                    count tricks twice for
  918.                                                    short-suitedness */
  919.                 }
  920.         }
  921.  
  922.         /* Add up points for the non-spades suits */
  923.   
  924.         for (i=DIAMONDS ; i<SPADES ; i++)  /* Loop thru suits */
  925.         {
  926.                 numsuit=0;
  927.                 suit=i*13;
  928.     
  929.                 /* Count cards for suit */
  930.     
  931.                 for (j=0 ; j<13 ; j++)
  932.                         if (Deck[suit+j]==player+1) numsuit++;
  933.                 
  934.                 /* Short-Suitedness */
  935.  
  936.                 if (numspades>2)
  937.                 {
  938.                         if (numsuit==0)
  939.                                 points+=8;
  940.                         else if (numsuit==1)
  941.                                 points+=4;
  942.                         else if (numsuit==2)
  943.                                 points+=2;
  944.                 }
  945.                 else if (numspades==2)
  946.                 {
  947.                         if (numsuit==0)
  948.                                 points+=5;
  949.                         else if (numsuit==1)
  950.                                 points+=2;
  951.                 }
  952.                 else if (numspades==1)
  953.                 {
  954.                         if (numsuit==0)
  955.                                 points+=3;
  956.                 }
  957.                 
  958.                 /* Add points for face cards */
  959.     
  960.                 if (Deck[suit+12]==player+1)    /* Ace   */
  961.                 {
  962.                         if (numsuit<6) points+=4;
  963.                         else if (numsuit<8) points+=2;
  964.                         else points+=1;
  965.                 }
  966.                 if (Deck[suit+11]==player+1)    /* King  */
  967.                 {
  968.                         if ((numsuit<5)&&(numsuit>1)) points+=4;
  969.                         else if ((numsuit<6)&&(numsuit>1)) points+=2;
  970.                         else if ((numsuit<7)&&(numsuit>1)) points+=1;
  971.                 }
  972.                 if (Deck[suit+10]==player+1)    /* Queen */
  973.                 {
  974.                         if (numsuit==3) points+=2;
  975.                 }
  976.         }
  977.   
  978.  
  979.         points+=Mode[player];        /* Adjust for aggressiveness */
  980.         if (points<4) points=4;      /* Validate number of points */
  981.         bid=points/4;                /* Find Bid */
  982.   
  983.         /* Make sure total team bid not greater than 13 */
  984.   
  985.         i=(player+2)%4;              /* Find partner */
  986.         if ((bid+Bid[i])>13) bid=13-Bid[i];
  987.   
  988.         /* Display Bid */
  989.   
  990.         itoa(bid,String);
  991.         SetAPen(RP,YELP);
  992.         SetBPen(RP,BLUP);
  993.         Move(RP,MsgX[player],MsgY[player]);
  994.         Text(RP,String,strlen(String));
  995.   
  996.         /* Send bid back */
  997.   
  998.         return(bid);
  999. }
  1000.  
  1001. /**********************************************************
  1002. * Function: PlayHand                                      *
  1003. * Parameters: none                                        *
  1004. * Return Values: none                                     *
  1005. * Purpose: Play out a hand until all 13 tricks are taken. *
  1006. **********************************************************/
  1007. void PlayHand()
  1008. {
  1009.         int i;
  1010.   
  1011.         /* Initialize */
  1012.   
  1013.         PlayerTricks=CompTricks=0;
  1014.         SpadePlayed=FALSE;
  1015.         PrintTricks();
  1016.   
  1017.         /* Loop through all 13 tricks */
  1018.   
  1019.         for (i=0 ; i<13 ; i++)
  1020.         {
  1021.                 TrickLead=TakeTrick();                /* Play a trick */
  1022.                 if ((TrickLead==0)||(TrickLead==2))   /* Who won? */
  1023.                         PlayerTricks++;
  1024.                 else
  1025.                         CompTricks++;
  1026.                 PrintTricks();         /* Display new trick total */
  1027.     
  1028.                 /* Indicate who won with an '*' */
  1029.     
  1030.                 SetAPen(RP,YELP);
  1031.                 SetBPen(RP,BLUP);
  1032.                 Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
  1033.                 Text(RP,"*",1);
  1034.     
  1035.                 /* Pause for click */
  1036.  
  1037.                 SetAPen(RP,YELP);
  1038.                 Move(RP,200,150);
  1039.                 Text(RP,"Click mouse",11);
  1040.                 ReadMouse();
  1041.                 Move(RP,200,150);
  1042.                 Text(RP,"           ",11);
  1043.     
  1044.                 /* Erase winner indicator */
  1045.     
  1046.                 Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
  1047.                 Text(RP," ",1);
  1048.         }
  1049.   
  1050.         /* Calculate new score */
  1051.   
  1052.         if (PlayerTricks<PlayerBid)
  1053.                 PlayerScore-=(10*PlayerBid);
  1054.         if (CompTricks<CompBid)
  1055.                 CompScore-=(10*CompBid);
  1056.         if (PlayerTricks>=PlayerBid)
  1057.                 PlayerScore+=((10*PlayerBid)+(PlayerTricks-PlayerBid));
  1058.         if (CompTricks>=CompBid)
  1059.                 CompScore+=((10*CompBid)+(CompTricks-CompBid));
  1060.     
  1061.         /* Pause for click */
  1062.  
  1063.         SetAPen(RP,YELP);
  1064.         Move(RP,200,150);
  1065.         Text(RP,"Click mouse",11);
  1066.         ReadMouse();
  1067.         Move(RP,200,150);
  1068.         Text(RP,"           ",11);
  1069. }
  1070.  
  1071. /**********************************************************
  1072. * Function: TakeTrick                                     *
  1073. * Parameters: none                                        *
  1074. * Return Values: winner of trick                          *
  1075. * Purpose: Each player plays a card, then determine trick *
  1076. *          winner.                                        *
  1077. **********************************************************/
  1078. int TakeTrick()
  1079. {
  1080.         int i,j,leadsuit,suit,value;
  1081.   
  1082.         /* Clear previously played cards */
  1083.   
  1084.         SetAPen(RP,BLUP);
  1085.         SetOPen(RP,BLUP);
  1086.         for (i=0 ; i<4 ; i++)
  1087.                 RectFill(RP,CardX[i],CardY[i],(CardX[i]+41),(CardY[i]+41));
  1088.   
  1089.         /* Get played cards */
  1090.   
  1091.         i=TrickLead;
  1092.         do
  1093.         {
  1094.                 if (!i)
  1095.                         Card[i]=GetPlayerCard();
  1096.                 else
  1097.                         Card[i]=GetCompCard(i);
  1098.                 if (i==TrickLead)      /* First card played wins so far */
  1099.                 {
  1100.                         HighCard=Card[i];
  1101.                         leadsuit=Card[i]/13;
  1102.                         Winner=i;
  1103.                 }
  1104.                 else
  1105.                 {
  1106.                         suit=Card[i]/13;
  1107.       
  1108.                         /* See if this card is the new winner */
  1109.       
  1110.                         if (((suit==leadsuit)||(suit==SPADES))&&(Card[i]>HighCard))
  1111.                         {
  1112.                                 HighCard=Card[i];
  1113.                                 Winner=i;
  1114.                         }
  1115.       
  1116.                         /* Was player out of the lead suit ? */
  1117.       
  1118.                         if (suit!=leadsuit) OutOfSuit[i][leadsuit]=TRUE;
  1119.                 }
  1120.                 i=(++i)%4;
  1121.         } while (i!=TrickLead);
  1122.   
  1123.         ShowHand();
  1124.   
  1125.         /* Set highest card played in each suit */
  1126.   
  1127.         for (i=0 ; i<4 ; i++)
  1128.         {
  1129.                 for (j=0 ; j<4 ; j++)    /* Need two loops to make sure we get all */
  1130.                 {
  1131.                         value=Card[j]%13;
  1132.                         suit=Card[j]/13;
  1133.                         if (value==HighCardLeft[suit]) HighCardLeft[suit]=value-1;
  1134.                 }
  1135.         }
  1136.   
  1137.         /* Send back trick winner */
  1138.   
  1139.         return(Winner);
  1140. }
  1141.  
  1142. /**********************************************************
  1143. * Function: GetPlayerCard                                 *
  1144. * Parameters: none                                        *
  1145. * Return Values: card picked to play                      *
  1146. * Purpose: Allow player to pick card to play.             *
  1147. **********************************************************/
  1148. int GetPlayerCard()
  1149. {
  1150.         int i,x,card;
  1151.   
  1152.         /* Let player know that it's his/her turn */
  1153.   
  1154.         SetBPen(RP,BLUP);
  1155.         SetAPen(RP,YELP);
  1156.         Move(RP,200,150);
  1157.         Text(RP,"PLAY A CARD",11);
  1158.   
  1159.         /* Loop until we get a good card */
  1160.   
  1161.         FOREVER
  1162.         {
  1163.                 ReadMouse();                         /* Wait for mouse click */ 
  1164.                 if (Button==MRIGHT) SuggestCard();   /* Player wants a suggestion */
  1165.                 if (Button==MLEFT)                   /* Did player pick a card ? */
  1166.                 {
  1167.                         for (i=12 ; i>=0 ; i--)      /* Check from right to left */
  1168.                         {
  1169.                                 x=(i*10)+21;         /* Set left corner for card */
  1170.         
  1171.                                 /* See if clicked inside this card and if card is still unplayed */
  1172.         
  1173.                                 if ((My<187)&&(My>144)&&(Mx<(x+42))&&(Mx>=x)&&(Hand[0][i]))
  1174.                                 {
  1175.                                         if (ValidCard(i))  /* Was this a playable card ? */
  1176.                                         {
  1177.                                                 card=Hand[0][i]-1;
  1178.                                                 Hand[0][i]=0;   /* Mark card as played */
  1179.                                                 if ((card/13)==SPADES) SpadePlayed=TRUE; /* Spades have been broken */
  1180.             
  1181.                                                 /* Erase suggestion '*' */
  1182.             
  1183.                                                 SetAPen(RP,BLUP);
  1184.                                                 SetOPen(RP,BLUP);
  1185.                                                 RectFill(RP,21,136,170,144);
  1186.             
  1187.                                                 DrawCard(CardX[0],CardY[0],card); /* Draw played card */
  1188.             
  1189.                                                 /* Erase prompt message */
  1190.             
  1191.                                                 SetBPen(RP,BLUP);
  1192.                                                 Move(RP,200,150);
  1193.                                                 Text(RP,"           ",11);
  1194.             
  1195.                                                 /* Send back played card */
  1196.             
  1197.                                                 return(card);
  1198.                                         }
  1199.                                         else
  1200.           
  1201.                                                 /* if chosen card was not valid, need a new card */
  1202.             
  1203.                                                 i=-1;
  1204.                                 }
  1205.                         }
  1206.                 }
  1207.         }
  1208. }
  1209.  
  1210. /**********************************************************
  1211. * Function: ValidCard                                     *
  1212. * Parameters: card -- card in player's hand to check      *
  1213. * Return Values: was card valid or not?                   *
  1214. * Purpose: To determine if the card chosen by the player  *
  1215. *   was valid or not.                                     *
  1216. **********************************************************/
  1217. BOOL ValidCard(card)
  1218. int card;
  1219. {
  1220.         int i,suit,leadsuit;
  1221.   
  1222.         SuitNumber[DIAMONDS]=0;
  1223.         SuitNumber[CLUBS]   =0;
  1224.         SuitNumber[HEARTS]  =0;
  1225.         SuitNumber[SPADES]  =0;
  1226.   
  1227.         /* Count number of cards player has in each suit */
  1228.   
  1229.         for (i=0 ; i<13 ; i++)
  1230.         {
  1231.                 if (Hand[0][i]) SuitNumber[(Hand[0][i]-1)/13]++;
  1232.         }
  1233.   
  1234.         suit=(Hand[0][card]-1)/13; /* Find suit of played card */
  1235.   
  1236.         if (!TrickLead)            /* Player is leading */
  1237.         {
  1238.                 /* If he didn't lead a spade, it was a good play */
  1239.                 if (suit!=SPADES) return(TRUE);
  1240.     
  1241.                 /* If he only has spades, he has no choice */ 
  1242.                 if ((!SuitNumber[0])&&(!SuitNumber[1])&&(!SuitNumber[2])) return(TRUE);
  1243.     
  1244.                 /* If spades have been played, he can lead anything */
  1245.                 if (SpadePlayed) return(TRUE);
  1246.     
  1247.                 /* Must have lead a spade when it was illegal to */
  1248.                 return(FALSE);
  1249.         }
  1250.   
  1251.         /* Player doesn't lead */
  1252.   
  1253.         leadsuit=Card[TrickLead]/13;       /* Find suit that was lead */
  1254.   
  1255.         /* If he played the suit that was lead, he is OK */
  1256.         if (suit==leadsuit) return(TRUE);
  1257.   
  1258.         /* If he didn't have any, he's OK */
  1259.         if (!SuitNumber[leadsuit]) return(TRUE);
  1260.   
  1261.         /* Must have had some but didn't play them */
  1262.         return(FALSE);
  1263. }
  1264.  
  1265. /**********************************************************
  1266. * Function: CountCards                                    *
  1267. * Parameters: none                                        *
  1268. * Return Values: none                                     *
  1269. * Purpose: Count cards in each suit for a player.         *
  1270. *   Determine short and long suits.                       *
  1271. **********************************************************/
  1272. void CountCards(player)
  1273. int player;
  1274. {
  1275.         int i,card,suit,maximum,minimum;
  1276.   
  1277.         /* Initialization */
  1278.   
  1279.         SuitNumber[DIAMONDS]=0;
  1280.         SuitNumber[CLUBS]   =0;
  1281.         SuitNumber[HEARTS]  =0;
  1282.         SuitNumber[SPADES]  =0;
  1283.   
  1284.         /* Loop through all cards in the player's hand */
  1285.   
  1286.         for (i=0 ; i<13 ; i++)
  1287.         {
  1288.                 if (Hand[player][i])        /* Make sure card hasn't been played */
  1289.                 {
  1290.                         card=Hand[player][i]-1;
  1291.                         suit=card/13;
  1292.                         Value[i]=13-card;         /* Give lower cards a slight priority */
  1293.                         SuitNumber[suit]++;       /* Count Number of Suit held */
  1294.                 }
  1295.                 else
  1296.                         Value[i]=-50000;          /* Don't throw previously played cards */
  1297.         }
  1298.   
  1299.         /* Find short and long suits */
  1300.   
  1301.         minimum=14;
  1302.         maximum=0;
  1303.         ShortSuit=LongSuit=3;
  1304.         for (i=DIAMONDS ; i<SPADES ; i++)
  1305.         {
  1306.                 if ((SuitNumber[i]<minimum)&&(SuitNumber[i]>0))
  1307.                 {
  1308.                         minimum=SuitNumber[i];
  1309.                         ShortSuit=i;
  1310.                 }
  1311.                 if (SuitNumber[i]>maximum)
  1312.                 {
  1313.                         maximum=SuitNumber[i];
  1314.                         LongSuit=i;
  1315.                 }
  1316.         }
  1317. }
  1318.   
  1319. /**********************************************************
  1320. * Function: SuggestCard                                   *
  1321. * Parameters: none                                        *
  1322. * Return Values: none                                     *
  1323. * Purpose: Suggest a card for player to play.             *
  1324. **********************************************************/
  1325. void SuggestCard()
  1326. {
  1327.         int i,pick,maximum;
  1328.   
  1329.         CountCards(0);
  1330.  
  1331.         /* Go to appropriate point calculating routine */
  1332.   
  1333.         if (!TrickLead)
  1334.                 CalcLead(0);
  1335.         else
  1336.                 CalcFollow(0);
  1337.   
  1338.         /* Find best card (the one with the most points) */
  1339.   
  1340.         pick=0;
  1341.         maximum=Value[0];
  1342.         for (i=1 ; i<13 ; i++)
  1343.         {
  1344.                 if (Value[i]>maximum)
  1345.                 {
  1346.                         maximum=Value[i];
  1347.                         pick=i;
  1348.                 }
  1349.         }
  1350.   
  1351.         /* Display an '*' over suggested card */
  1352.   
  1353.         SetAPen(RP,YELP);
  1354.         SetBPen(RP,BLUP);
  1355.         Move(RP,((pick*10))+22,142);
  1356.         Text(RP,"*",1);
  1357. }
  1358.  
  1359. /**********************************************************
  1360. * Function: GetCompCard                                   *
  1361. * Parameters: player -- player to play                    *
  1362. * Return Values: card played                              *
  1363. * Purpose: Determine which card a computer-controlled     *
  1364. *   player will play.                                     *
  1365. **********************************************************/
  1366. int GetCompCard(player)
  1367. int player;
  1368. {
  1369.         int i,pick,card,maximum;
  1370.   
  1371.         CountCards(player);
  1372.  
  1373.         /* Go to appropriate point calculating routine */
  1374.   
  1375.         if (player==TrickLead)
  1376.                 CalcLead(player);
  1377.         else
  1378.                 CalcFollow(player);
  1379.   
  1380.         /* Find best card (the one with the most points) */
  1381.   
  1382.         pick=0;
  1383.         maximum=Value[0];
  1384.         for (i=1 ; i<13 ; i++)
  1385.         {
  1386.                 if (Value[i]>maximum)
  1387.                 {
  1388.                         maximum=Value[i];
  1389.                         pick=i;
  1390.                 }
  1391.         }
  1392.   
  1393.         card=Hand[player][pick]-1;
  1394.         if ((card/13)==3) SpadePlayed=TRUE;  /* Mark that spades have been broken */
  1395.         Hand[player][pick]=0;                /* Card has now been played */
  1396.         DrawCard(CardX[player],CardY[player],card);  /* Draw the played card */
  1397.         return(card);                        /* Send the played card back */
  1398. }
  1399.  
  1400. /**********************************************************
  1401. * Function: CalcLead                                      *
  1402. * Parameters: player -- whose hand to calculate           *
  1403. * Return Values: none                                     *
  1404. * Purpose: To calculate the value of each card in a hand  *
  1405. *          to determine which card should be played if    *
  1406. *          the hand is leading.                           *
  1407. **********************************************************/
  1408. void CalcLead(player)
  1409. int player;
  1410. {
  1411.         int i,card,suit,value;
  1412.         BOOL opponentsout=FALSE, partnerout=FALSE;
  1413.   
  1414.         /* Loop through all cards in hand */
  1415.   
  1416.         for (i=0 ; i<13 ; i++)
  1417.         {
  1418.                 if (Hand[player][i])   /* Make sure card hasn't been played */
  1419.                 {
  1420.       
  1421.                         /* Find suit and face value */
  1422.       
  1423.                         card=Hand[player][i]-1;
  1424.                         suit=card/13;
  1425.                         value=card%13;
  1426.       
  1427.                         if ((OutOfSuit[(player+1)%4][suit])||(OutOfSuit[(player+3)%4][suit]))
  1428.                                 opponentsout=TRUE;
  1429.         
  1430.                         if (OutOfSuit[(player+2)%4][suit])
  1431.                                 partnerout=TRUE;
  1432.       
  1433.                         if (value==HighCardLeft[suit])  /* Card is highest left in a suit */
  1434.                         {
  1435.                                 if (suit==SPADES)       /* Spades don't matter if someone is */
  1436.                                         Value[i]+=50;   /* out. */
  1437.                                 else
  1438.                                 {  
  1439.                                         /* If opponents are out
  1440.                                            (or likely to be), don't waste */
  1441.                                         if ((opponentsout)||(value<11))
  1442.                                                 Value[i]-=50;   /* high cards. */
  1443.                                         else
  1444.                                                 Value[i]+=500;
  1445.                                 }  
  1446.                         }
  1447.       
  1448.                         /* If player holds spades, get rid of short suit */
  1449.                         if ((SuitNumber[SPADES])&&(suit==ShortSuit)) Value[i]+=250;
  1450.       
  1451.                         /* If player doesn't hold spades, get rid of long suit */
  1452.                         if ((!SuitNumber[SPADES])&&(suit==LongSuit)) Value[i]+=250;
  1453.       
  1454.                         /* If spades aren't broken, they can't be lead */
  1455.                         if ((suit==SPADES)&&(!SpadePlayed)) Value[i]-=5000;
  1456.       
  1457.                         /* Lead suits your partner is out of */
  1458.                         if ((suit!=SPADES)&&(partnerout)&&(!opponentsout)) Value[i]+=100;
  1459.                 }
  1460.         }
  1461. }
  1462.  
  1463. /**********************************************************
  1464. * Function: CalcFollow                                    *
  1465. * Parameters: player -- whose hand to calculate           *
  1466. * Return Values: none                                     *
  1467. * Purpose: To calculate the value of each card in a hand  *
  1468. *          to determine which card should be played if    *
  1469. *          the hand is not leading.                       *
  1470. **********************************************************/
  1471. void CalcFollow(player)
  1472. int player;
  1473. {
  1474.         int i,card,suit,value,leadsuit;
  1475.         BOOL alreadywon;
  1476.   
  1477.         leadsuit=Card[TrickLead]/13;  /* Calculate the suit that was lead */
  1478.   
  1479.         /* See if partner has already won the trick */
  1480.   
  1481.         alreadywon=FALSE;
  1482.         /* See if win is guaranteed (player is last to play) */
  1483.         if ((Winner==((player+2)%4))&&(TrickLead==((player+1)%4)))
  1484.                 alreadywon=TRUE;  
  1485.     
  1486.         /* See if win is probable (player is next to last to play) */
  1487.         if ((Winner==TrickLead)&&(TrickLead==((player+2)%4)))
  1488.         {
  1489.                 value=Card[TrickLead]%13;
  1490.                 if ((value==HighCardLeft[leadsuit])&&(value>9)&&
  1491.                     !OutOfSuit[(player+3)%4][leadsuit]) alreadywon=TRUE;
  1492.         }
  1493.  
  1494.         /* Loop through all cards in hand */
  1495.   
  1496.         for (i=0 ; i<13 ; i++)
  1497.         {
  1498.                 if (Hand[player][i])  /* Make sure card hasn't been played */
  1499.                 {
  1500.       
  1501.                         /* Find suit and face value of card */
  1502.       
  1503.                         card=Hand[player][i]-1;
  1504.                         suit=card/13;
  1505.                         value=card%13;
  1506.       
  1507.                         if (suit==leadsuit)   /* Card is of lead suit */
  1508.                         { 
  1509.                                 Value[i]+=5000;
  1510.         
  1511.                                 /* If it is the highest one left in that suit, throw it */
  1512.                                 if ((value==HighCardLeft[suit])&&(TrickLead!=((player+1)%4))&&(card>HighCard)&&!OutOfSuit[(player+1)%4][suit])
  1513.                                         Value[i]+=70;
  1514.           
  1515.                                 /* See if card will beat those previously played */
  1516.                                 if (card>HighCard)
  1517.                                 {
  1518.                                         if (!alreadywon)  /* Team hasn't won yet */  
  1519.                                         {
  1520.                                                 if (TrickLead==((player+1)%4))  /* Can definitely take trick */
  1521.                                                         Value[i]+=100;
  1522.                                                 else                 
  1523.                                                         Value[i]+=10;   /* Maybe take trick */
  1524.                                         }    
  1525.                                         else
  1526.                                                 Value[i]-=75;   /* If the team has won, hold high cards */
  1527.                                 }
  1528.         
  1529.                                 /* If team has already won the trick, throw low cards */
  1530.                                 if ((card<HighCard)&&alreadywon) Value[i]+=75;
  1531.                         }
  1532.       
  1533.                         /* If player is going to throw a spade, make sure it has a chance of
  1534.                            winning */
  1535.                         if ((suit==SPADES)&&(card>HighCard))
  1536.                         {
  1537.                                 if (!alreadywon)
  1538.                                         Value[i]+=10;   /* If team hasn't won, throw the spade */
  1539.                                 else
  1540.                                         Value[i]-=1000; /* If team has won, hold high spades */
  1541.                         }
  1542.                         if ((suit==SPADES)&&(card<HighCard))
  1543.                         {
  1544.                                 if (!alreadywon)
  1545.                                         Value[i]-=1000; /* If the team hasn't won, don't throw a losing spade */
  1546.                                 else
  1547.                                         Value[i]+=10;   /* If the team has one, throw a low spade */
  1548.                         }
  1549.       
  1550.                         /* If player is out of the lead suit, don't throw important cards
  1551.                            in other suits */
  1552.                         if ((suit!=leadsuit)&&(value==HighCardLeft[suit])) Value[i]-=100;
  1553.       
  1554.                         /* If player is out of lead suit, let's see about trumping */
  1555.                         if ((!SuitNumber[leadsuit])&&(suit==SPADES))
  1556.                         {
  1557.                                 if (!alreadywon)
  1558.                                         Value[i]+=100;  /* If team hasn't won, trump */
  1559.                                 else
  1560.                                         Value[i]-=1000; /* If team has won, no need to trump */
  1561.                         }
  1562.       
  1563.                         /* If player is out of lead suit and out of spades, throw the long
  1564.                            suit left (keep as many suits as possible in hand) */
  1565.                         if ((!SuitNumber[leadsuit])&&(!SuitNumber[SPADES])&&(suit==LongSuit))
  1566.                         {
  1567.                                 Value[i]+=100;
  1568.                         }
  1569.       
  1570.                         /* Give short suit a priority */
  1571.                         if (suit==ShortSuit) Value[i]+=45;
  1572.                 }
  1573.         }
  1574. }
  1575.  
  1576. /**********************************************************
  1577. * Function: PrintBids                                     *
  1578. * Parameters: none                                        *
  1579. * Return Values: none                                     *
  1580. * Purpose: Display the number of tricks bid by each team  *
  1581. *          in the score box.                              *
  1582. **********************************************************/
  1583. void PrintBids()
  1584. {
  1585.         int length=0;
  1586.   
  1587.         SetAPen(RP,GRNP);
  1588.         SetBPen(RP,BLKP);
  1589.         itoa(PlayerBid,String);
  1590.         length=strlen(String);
  1591.         Move(RP,(235-(4*length)),38);
  1592.         Text(RP,String,length);
  1593.         itoa(CompBid,String);
  1594.         length=strlen(String);
  1595.         Move(RP,(283-(4*length)),38);
  1596.         Text(RP,String,length);
  1597. }
  1598.  
  1599. /**********************************************************
  1600. * Function: PrintScore                                    *
  1601. * Parameters: none                                        *
  1602. * Return Values: none                                     *
  1603. * Purpose: Display each team's score in the score box.    *
  1604. **********************************************************/
  1605. void PrintScore()
  1606. {
  1607.         int length=0;
  1608.   
  1609.         SetAPen(RP,GRNP);
  1610.         SetBPen(RP,BLKP);
  1611.         itoa(PlayerScore,String);
  1612.         length=strlen(String);
  1613.         Move(RP,(235-(4*length)),22);
  1614.         Text(RP,String,length);
  1615.         itoa(CompScore,String);
  1616.         length=strlen(String);
  1617.         Move(RP,(283-(4*length)),22);
  1618.         Text(RP,String,length);
  1619. }
  1620.  
  1621. /**********************************************************
  1622. * Function: PrintTricks                                   *
  1623. * Parameters: none                                        *
  1624. * Return Values: none                                     *
  1625. * Purpose: Display the number of tricks taken by each     *
  1626. *          team in the score box.                         *
  1627. **********************************************************/
  1628. void PrintTricks()
  1629. {
  1630.         int length=0;
  1631.   
  1632.         SetAPen(RP,GRNP);
  1633.         SetBPen(RP,BLKP);
  1634.         itoa(PlayerTricks,String);
  1635.         length=strlen(String);
  1636.         Move(RP,(235-(4*length)),54);
  1637.         Text(RP,String,length);
  1638.         itoa(CompTricks,String);
  1639.         length=strlen(String);
  1640.         Move(RP,(283-(4*length)),54);
  1641.         Text(RP,String,length);
  1642. }
  1643.  
  1644. /**********************************************************
  1645. * Function: ReadMouse                                     *
  1646. * Parameters: none                                        *
  1647. * Return Values: none                                     *
  1648. * Purpose: Wait for mouse input, and update the mouse     *
  1649. *          variables accordingly.                         *
  1650. **********************************************************/
  1651. void ReadMouse()
  1652. {
  1653.         ULONG class;
  1654.         USHORT code;
  1655.         BOOL gotmouse=FALSE;
  1656.  
  1657.         /* Loop until we have a mouse message */
  1658.   
  1659.         while(!gotmouse)
  1660.         {
  1661.     
  1662.                 /* Wait for Intuition Message */
  1663.     
  1664.                 if ((Message=(struct IntuiMessage *) GetMsg(Wdw->UserPort)) == NULL)
  1665.                 { 
  1666.                         Wait(1L<<Wdw->UserPort->mp_SigBit);
  1667.                         continue;
  1668.                 }
  1669.     
  1670.                 /* Interpret Message */
  1671.     
  1672.                 class = Message->Class;
  1673.                 code = Message->Code;
  1674.                 Mx=((SHORT) Message->MouseX) - 4;  /* Adjustments for      */
  1675.                 My=((SHORT) Message->MouseY) - 12; /* GIMMEZEROZERO Window */
  1676.  
  1677.                 ReplyMsg((struct Message *)Message);
  1678.  
  1679.                 /* See if Window Close Box clicked */
  1680.     
  1681.                 if (class & CLOSEWINDOW) WrapUp();
  1682.  
  1683.                 /* See if Hide Gadget clicked */
  1684.                 
  1685.                 if (class & GADGETUP) 
  1686.                 {
  1687.                         ScreenToBack(CustScr);
  1688.                         return;
  1689.                 }
  1690.                                 
  1691.                 /* Otherwise, make sure Message was caused by mouse */
  1692.     
  1693.                 if (class & MOUSEBUTTONS)
  1694.                 {
  1695.                         switch(code)
  1696.                         {
  1697.         
  1698.                                 /* Left Button Released */
  1699.         
  1700.                                 case SELECTUP:
  1701.                                         Button=MLEFT;
  1702.                                         gotmouse=TRUE;
  1703.                                         break;
  1704.         
  1705.                                 /* Right Button Released */
  1706.         
  1707.                                 case MENUUP:   
  1708.                                         Button=MRIGHT;
  1709.                                         gotmouse=TRUE;
  1710.                                         break;
  1711.            
  1712.                                 /* Other Input */
  1713.         
  1714.                                 default:
  1715.                                         gotmouse=FALSE;
  1716.                         }   
  1717.                 }
  1718.         }
  1719.  
  1720. /**********************************************************
  1721. * Function: DrawCard                                      *
  1722. * Parameters: x -- x coordinate of top left corner        *
  1723. *             y -- y coordinate of top left corner        *
  1724. *           card -- number of card to draw                *
  1725. * Return Values: none                                     *
  1726. * Purpose: Draw a card.                                   *
  1727. **********************************************************/   
  1728. void DrawCard(x, y, card)
  1729. int x, y, card;
  1730. {
  1731.         CardImage.ImageData = (UWORD *)(CardData+card*126*6);
  1732.         DrawImage(RP, &CardImage, x, y);
  1733. }
  1734.  
  1735. /**********************************************************
  1736. * Function: FinishRoutine                                 *
  1737. * Parameters: none                                        *
  1738. * Return Values: none                                     *
  1739. * Purpose: Display final score, ask to play again.        *
  1740. **********************************************************/
  1741. void FinishRoutine()
  1742. {
  1743.         BOOL haveinput;
  1744.   
  1745.         SetRast(RP,BLUP);
  1746.   
  1747.         SetAPen(RP,WHTP);
  1748.         SetBPen(RP,BLUP);
  1749.   
  1750.         Move(RP,112,56);
  1751.         Text(RP,"FINAL SCORE:",12);
  1752.         Move(RP,80,72);
  1753.         Text(RP,"YOU:",4);
  1754.         Move(RP,184,72);
  1755.         Text(RP,"ME:",3);
  1756.         SetAPen(RP,YELP);
  1757.         itoa(PlayerScore,String);
  1758.         Move(RP,116,72);
  1759.         Text(RP,String,strlen(String));
  1760.         itoa(CompScore,String);
  1761.         Move(RP,212,72);
  1762.         Text(RP,String,strlen(String));
  1763.   
  1764.         Move(RP,112,96);
  1765.         Text(RP,"PLAY AGAIN ?",12);
  1766.         SetAPen(RP,BLKP);
  1767.         SetBPen(RP,WHTP);
  1768.         Move(RP,112,112);
  1769.         Text(RP,"YES",3);
  1770.         Move(RP,188,112);
  1771.         Text(RP,"NO",2);
  1772.   
  1773.         haveinput=FALSE;
  1774.         while (!haveinput)
  1775.         {
  1776.                 ReadMouse();
  1777.                 if ((Mx>111)&&(Mx<136)&&(My>105)&&(My<114))
  1778.                 {
  1779.                         haveinput=TRUE;
  1780.                         AllDone=FALSE;
  1781.                 }
  1782.                 if ((Mx>187)&&(Mx<204)&&(My>105)&&(My<114))
  1783.                 {
  1784.                         haveinput=TRUE;
  1785.                         AllDone=TRUE;
  1786.                 }
  1787.         }
  1788. }
  1789.  
  1790. /**********************************************************
  1791. * Function: itoa                                          *
  1792. * Parameters: n -- number to convert                      *
  1793. *             s -- pointer to result string               *
  1794. * Return Values: none                                     *
  1795. * Purpose: Convert an integer to a string so it can be    *
  1796. *          used by the Text function. Lattice does not    *
  1797. *          have one.                                      *
  1798. **********************************************************/
  1799. void itoa(n,s)
  1800. char *s;
  1801. int n;
  1802. {
  1803.         int i=0;
  1804.         BOOL sign=FALSE;
  1805.   
  1806.         if (n<0)
  1807.         {
  1808.                 sign=TRUE;
  1809.                 n=-n;
  1810.         }
  1811.         do
  1812.         {
  1813.                 s[i++]=n%10+'0';
  1814.         } while((n/=10)>0);
  1815.         if (sign) s[i++]='-';
  1816.         s[i]='\0';
  1817.         strrev(s);
  1818. }
  1819.